前三天講了生產線怎麼分工、資料要先講好長什麼樣。今天要處理一個比較實際的工程問題:這套系統裡,負責幾何運算的是 Python,負責網頁呈現的是 JavaScript,兩種語言、兩套套件生態,卻要放進同一個 repo 一起開發,怎麼讓它們不互相干擾?
做法是 monorepo,但雙 workspace 共存:Python 那邊用 uv 管,pyproject.toml 裡 [tool.uv.workspace] 把 contracts、packages/*、packs/*、agents 都收進來;JavaScript 那邊用 pnpm,pnpm-workspace.yaml 只列 Node 相關的套件(例如負責網頁封裝、瀏覽器渲染的那幾個)。兩邊各自用自己熟悉的方式管版本、管依賴,互不干涉,最上層用一支 justfile 把常用指令(setup、check、test)串起來,開發者不用記兩套指令。
好處是:Python 那邊要升級某個幾何運算套件,不會動到 JavaScript 那邊的 lockfile;反過來也一樣。但兩邊仍然共用同一份東西——Day 03 講的那份資料契約(JSON Schema),透過程式碼產生器(codegen)分別產出 Python 用的 Pydantic 模型跟 TypeScript 用的型別定義。這樣兩邊永遠是同一份定義展開出來的,不會各說各話。CI 裡有一道檢查專門確認「schema 改了、但忘記重新產生型別」這種情況不會被漏掉。
Day 02 提到的那幾條分工規則(例如「通用的處理流程不能知道自己在服務哪個垂直場景」「AI 相關的套件只能出現在特定資料夾」),光寫在文件裡沒有用——人會忘記,也會為了圖方便抄捷徑。所以這裡把規則寫成一支邊界檢查程式,對整個 repo 掃過去,一共抓四類問題:
這支檢查跑不過,這次的修改就不能算完成——跟寫測試的邏輯一樣,只是檢查的對象換成「架構有沒有被破壞」,而不是「功能對不對」。實務上這種規則寫起來會踩到不少字串比對的細節(例如某個關鍵字剛好是另一個正常詞彙的一部分,導致誤判),這部分留到之後有具體案例時再細講。
因為這幾件事(雙 workspace、契約產生型別、邊界檢查)越晚補,代價越高——晚一點加,等於要把已經寫壞的東西全部找出來改掉。先把這層「地基工程」搭好,之後每加一個新功能,才不用擔心一改就牽連到整個系統。明天開始,會用第一個真正的模型跑過整條生產線。